#!/usr/bin/python

from multiplylib import *

# ============================== for 8x8/16x16 mix multiply ==============================
dots_grid_init(cols=32, rows=12)

dots_8x8_L = gen_pp(mcand_width=8, mplier_width=8, prefix="", pp0_height_reduction=False)
# set the last pp (not pp[4] but pp_8_L[4])
pp_8_L_4 = [("pp_8_L[4][%d]" % i,False) for i in range(8)]
set_pp(dots_8x8_L, row=5, start_col=8, pp_val=pp_8_L_4)
# # ext to 32 bits
# for col in range(16, 32):
#     set_dots_cell(dots_8x8_L, (0, col), ("1'b1", True))
# set_dots_cell(dots_8x8_L, (1, 16), ("Sc", True))


# the dots only for "dot product"
dots_8x8_H_orig = gen_pp(mcand_width=8, mplier_width=8, prefix="", pp0_height_reduction=False, pp_index_start=(4,8))
dots_dotp_only = set_switch(dots_8x8_H_orig, "i_dotp") # the dots of dots_8x8_H_orig only valid when i_dotp asserted ("and" operation)

# the high 8x8 (only preverse the low 8 bits of the product)
dots_8x8_H = gen_pp(mcand_width=8, mplier_width=8, prefix="", pp0_height_reduction=True, pp_index_start=(4,8)) 

# strip the high half bits
for col in range(8,15+1):
    for row in range(12):
        set_dots_cell(dots_8x8_H, (row, col), (0, False))
shift_left(dots_8x8_H, 16)

dots_8x8 = add_dots(dots_8x8_L, dots_dotp_only, dots_8x8_H)
# dots_8x8 = add_dots(dots_8x8_L, dots_8x8_H)

set_dots_cell(dots_8x8, (3, 14), ("i_dotp", True)) # this cell must be "i_dotp"
# at least one of bellow cells should be set
set_dots_cell(dots_8x8, (0, 9), ("i_dotp", True))
set_dots_cell(dots_8x8, (1, 10), ("i_dotp", True))
set_dots_cell(dots_8x8, (2, 12), ("i_dotp", True))


new_fig()
display_dots(dots_8x8, style="text")

mark_dots(start_dot=(0,15), end_dot=(5,0), color="red")
mark_dots(start_dot=(6,15), end_dot=(11,0), color="blue")
mark_dots(start_dot=(0,23), end_dot=(4,16), color="red")

mark_dots(start_dot=(3,14), color="green")
mark_dots(start_dot=(0,9), color="green")
mark_dots(start_dot=(1,10), color="green")
mark_dots(start_dot=(2,12), color="green")

mark_dots(start_dot=(6,9), color="green")
mark_dots(start_dot=(7,10), color="green")
mark_dots(start_dot=(8,12), color="green")
mark_dots(start_dot=(9,14), color="green")


# simplify the i_dotp variable
set_dots_cell(dots_8x8, (0, 9), (0, False))
set_dots_cell(dots_8x8, (1, 10), (0, False))
set_dots_cell(dots_8x8, (2, 12), (0, False))
set_dots_cell(dots_8x8, (3, 14), (0, False))

set_dots_cell(dots_8x8, (6, 9), (0, False))
set_dots_cell(dots_8x8, (7, 10), (0, False))
set_dots_cell(dots_8x8, (8, 12), (0, False))
set_dots_cell(dots_8x8, (9, 14), (0, False))

set_dots_cell(dots_8x8, (6, 15), ("i_dotp", True))
set_dots_cell(dots_8x8, (6, 13), ("i_dotp", True))
set_dots_cell(dots_8x8, (6, 11), ("i_dotp", True))
set_dots_cell(dots_8x8, (6, 10), ("i_dotp", True))

# # don't care term
# for col in range(24,31+1):
#     for row in range(12):
#         set_dots_cell(dots_8x8, (row, col), ('X', True))
    

new_fig()
display_dots(dots_8x8, style="text")

mark_dots(start_dot=(0,15), end_dot=(5,0), color="red")
mark_dots(start_dot=(6,15), end_dot=(11,0), color="blue")
mark_dots(start_dot=(0,23), end_dot=(4,16), color="red")
mark_dots(start_dot=(6,15), end_dot=(6,10), color="green")



dots_8x8_up = reorg_upward(dots_8x8)
# new_fig()
# display_dots(dots_8x8_up, style="dot")


# 16x16 for Half word insn or fixed-point insn
dots_16x16 = gen_pp(mcand_width=16, mplier_width=16, prefix="")
# for round when in fixed point mode          ---- add it at the last 
set_dots_cell(dots_16x16, (9, 14), ("round", True))
# only for round mode of msub of fixed point num
for col in range(15,31+1):
    set_dots_cell(dots_16x16, (9, col), ("msub_round", True))

dots_16x16_up =reorg_upward(dots_16x16)

new_fig()
display_dots(dots_16x16, style="text")
mark_dots(start_dot=(9,14), end_dot=(9,31))


new_fig()
display_dots(dots_8x8_up, style="dot")
display_dots(dots_16x16_up, fill=False, color="red", style="dot")



# process the not-care term
for col in range(24,31+1):
    for row in range(12):
        dots_8x8_up[row][col] = dots_16x16_up[row][col]


dots_mix, dots_mix_distr = mix_dots(dots_8x8_up, dots_16x16_up, "mode8")

new_fig("distribute of 8x8/16x16 dots")
display_dots_distribute(dots_mix_distr)

# strip the redundancy term
def dot_process(item):
    if item.find("(mode8 & (i_dotp &") == 0:
        return item[9:-1]
    elif item == "(~mode8 & msub_round)":
        return "msub_round"
    
traverse_dots(dots_mix, dot_process)


new_fig()
display_dots(dots_mix, style="text")

print "==================== row formula of 8x8/16x16 mix multiply ===================="
print_row_formula(dots_mix, prefix="assign pp_ext")
print "==============================================================================="


# wallace tree compress
wallace_init(dots_mix)
cnt = 0
while True:
    new_fig()
    # display_dots(dots_mix, style="text")
    display_dots(dots_mix, style="dot") 
    if is_compress_finish():
        break
    cnt += 1
    compress_groups = wallace_compress()
    display_compress_groups(compress_groups)
    
print "total need %d stages to compress" % cnt
print_compress_sverilog_code()



show()
exit()





# only for round of mul/madd/msub when in fixed point mode
set_dots_cell(dots_mix, (9, 14), ("round", True))
# only for round of msub of fixed point num
for col in range(15,31+1):
    set_dots_cell(dots_mix, (9, col), ("msub_round", True))

fig6, ax6 = new_fig()
display_dots(dots_mix, style="text")
mark_dots(start_dot=(9,14), end_dot=(9,31))

dots_mix = reorg_upward(dots_mix)
# new_fig()
# display_dots(dots_mix, style="text")

# # dot product must use in 8x8 mode
# # strip "(mode8 & (i_dotp & pp[x][x]))" down to "(i_dotp & pp[x][x])"
# for i in all_dots(dots_mix):
#     if i[0] != 0 and i[0].find("(mode8 & (i_dotp &") == 0:
#         print (i[0][9:-1], i[1])
def dot_process(item):
    if item.find("(mode8 & (i_dotp &") == 0:
        return item[9:-1]
    
traverse_dots(dots_mix, dot_process)

new_fig()
display_dots(dots_mix, style="text")


# print "==================== row formula of 8x8/16x16 mix multiply ===================="
# print_row_formula(dots_mix, prefix="assign pp_ext")
# print "==============================================================================="






show()
exit()
